5W - 서비스 메시
개요
서비스 메시는 다양한 서비스가 그물망처럼 다양하게 얽히고 연결되어 있는 구조, 아키텍처를 말한다.
큰 서비스의 관점에서, 서비스 메시는 네트워크만을 따로 담당하는 추상된 인터페이스 레이어를 가진다는 것이 핵심이다.
서비스 메시는 아키텍처 개념인 만큼 독립된 서비스들을 운용하며 이들을 효율적으로, 장애가 전파되지 않도록 운영하는 기술과 방식도 포함하여 일컫는다.
대표적인 서비스 메시 툴에는 Istio가 있다.
이 개념을 익숙치 않다면, 등장 배경을 먼저 아는 것이 좋다.
용어 정리 - 어플리케이션과 서비스의 차이
클라우드 네이티브가 활성화되면서 어플리케이션과 서비스라는 용어가 많이 나오기 시작했다.
둘 다 비슷한 뜻이기는 하지만, 그래도 서비스 메시를 이해하기 위해서 먼저 두 용어를 간단하게 개념 차이를 짚을 필요가 있다.
어플리케이션
먼저 어플리케이션은 어떤 기능을 하는 프로그램이며, 이것을 만드는 사람이 바로 개발자이다.
웹어플리케이션을 만들기 위해서는 먼저 어떤 것을 하고자 하는지 기능 정의를 할 필요가 있다.
이 기능에 대한 로직을 만드는 것이 바로 개발의 행위이며, 조직의 업무 세분화를 통해 흔히 개발팀을 꾸려서 이 작업을 수행한다.
서비스
이 어플리케이션을 실제 사용자가 사용할 수 있도록 구축한 환경을 포함하는 개념이 서비스이다.
어플리케이션을 만들었으면 클라이언트가 이것을 활용할 수 있도록 시스템을 구축해야 한다.
사용할 수 있는 엔드포인트를 노출시키고, 도메인을 등록하거나 적절한 자원을 배치하는 운영적 요소가 결합된, 어플리케이션이 실제로 목적대로 사용될 수 있도록 하는 일련의 모든 과정이 들어간 개념이 서비스라고 할 수 있다.
인프라에 대한 개념이 들어가기 때문에 이 서비스를 담당하는 것은 운영팀이라고 할 수 있겠다.
서비스를 제공하는 실재적인 대상을 서버라고 정리할 수 있다.
흔히 웹서버라고 한다면 어플리케이션 구동뿐 아니라, 이 어플리케이션을 어떤 포트와 주소로 접근할 수 있게 하는지에 대한 개념도 들어가기 마련이다.
그래서 서비스에는 필연적으로 네트워크적인 요소가 들어가게 된다.
이러한 개념 정리 아래, 왜 우리가 마이크로 어플리케이션 아키텍처라고 하지 않고 마이크로서비스 아키텍처라고 하는지도 이해할 수 있다.
작은 기능 단위로 여러 어플리케이션을 책임지는 서비스를 분리하고, 이를 통합적으로 구성하여 궁극적인 시스템을 구축한 것이 바로 마이크로서비스 아키텍처이다.
여기에는 각 어플리케이션들을 네트워크로 긴밀하게 연결하는 과정이 필수적으로 들어가는데, 그렇기에 이 단위들은 서비스라고 부르는 것이 더 바람직하다.
이 문서에서 애플리케이션과 서비스를 명확하게 구분하는 이유는 비즈니스 조직 속에서 업무 대상에 대한 관심 분리를 명확하게 나누기 위해서이다.
흔히 개발팀, 운영팀으로 나누어진 조직을 생각해봤을 때 이 두 개념을 조금 더 명확히 구분할 수 있다.
간단하게 말하면 어플리케이션, 비즈니스 로직을 담당하는 팀은 개발팀이다.
반면 그렇게 만들어진 어플리케이션을 실제로 배포하고 발생할 수 있는 다양한 이슈들을 처리해나가는 팀은 운영팀이다.
배경 - 마이크로서비스아키텍쳐의 문제
컨테이너 기술이 본격화되며 어플리케이션을 패키징하는 것이 용이해졌고, 이런 컨테이너를 여러 노드에서 통합적으로 관리할 수 있도록 오토스케일링과 자동화 기능을 하는 컨테이너 오케스트레이션(대표적으로 쿠버네티스) 기술이 발달했다.
이로부터 유연한 확장성을 확보할 수 있는 MSA도 자연스럽게 정립됐다.
MSA의 가장 큰 특징 중 하나는 인프라 환경과 어플리케이션의 결합도를 낮춘다는 것으로, 물리적 자원의 제약에서 벗어나 자유롭게 기능을 확장하고 대처하는 것이 가능해졌다.
그러나 MSA 역시 몇 가지 문제점을 야기한다.
모놀리틱 아키텍처와 비교했을 때, 전체 아키텍쳐가 세분화되기에 구조는 복잡해지고 관리포인트가 늘어나게 된다.
현대 MSA에서 마주칠 수 있는 큰 문제점을 정리해보자.
- 트래픽 추적의 어려움
- 하나의 비즈니스 요청이 여러 개의 서비스를 거쳐가다보면 문제가 발생해도 어디에서 발생하는지 추적하기 어렵다.
- 어떤 서비스에서 요청 처리 시간이 길어지거나 에러가 발생하는지 파악하기 위해 각 서비스를 일일히 분석해야 할 수도..
- 이 문제는 자원을 대여받는 클라우드 인프라 환경에서 더욱 커진다.
- 문제가 발생해도 이게 어플리케이션 문제인지, 인프라 상의 문제인지 추적이 더 어려워진다!
- 각기 다른 개발 환경을 가진 서비스
- MSA 덕분에 특정 언어에 구애받지 않고 다양한 언어에 기반한 어플리케이션을 함께 운용할 수 있게 됐지만, 이것도 디버깅을 어렵게 하는 요소가 되기도 한다.
- 또 각 서비스를 개발하는 팀이 달라지면 각기 다른 배포 전략과 보안 정책을 수립하기도 하기에 다양한 문제가 파생된다.
- 각기 다른 보안 정책으로 인한 통합의 어려움과 이로 인한 공격 표면 확장
- 배포 간 자동화된 테스트 구축이 어려워짐
간단하게 정리했지만, 각각을 더 세분화시켜 문제점으로 삼을 수도 있을 만큼 운영 상에 굵직한 이슈들이라 할 수 있다.
해결 방안과 방향성
그러면 종합해서 현대 MSA에서 마주하는 도전과제들과 이를 위한 방법들도 간단하게 정리해보자.
- 서비스 안정성을 위한 자동화 구축
- 의도되지 않은 문제가 발생해도 서비스에 지장이 없도록 하는 복원력(resiliency) 확보를 위한 다양한 방법
- 클라이언트 사이드 로드밸런싱 - 여러 엔드포인트를 제공하고, 가능한 엔드포인트로 알아서 요청하도록 하기
- 서비스 디스커버리 - 논리적 서비스의 건강한 엔드포인트들을 주기적으로 리스트 업하기
- bulkheading - 클라마다 자원 사용량(커넥션 횟수, 스레드, 세션 등)을 제한
- 타임아웃 - 트래픽이나 요청의 최대 시간을 걸어서 에러낼 거면 빠르게 내기
- 재시도 - 실패한 요청을 알아서 재시도
- 데드라인 - 요청에 대한 응답의 수명 지정
- 관측 가능성 확보
- 자동화하여 안정성을 높여도, 궁극적으로는 어디에서 문제가 발생하는지 파악을 할 수 있도록 모니터링이 돼야 한다.
- 흔히 메트릭, 로그, 트레이싱이 필요할 텐데, MSA에서 특히 어려우면서 중요한 것은 트레이싱이라 할 수 있다.
- 트래픽이 이리저리 돌아다니면서 문제가 생기는 포인트를 명확하게 확인하기 위한 추적 수단이 필요하다!
근데.. 위 요소들을 누가 맡아서 작업을 수행해야 하는가?
서비스 메시가 등장하기 이전에는, 당연히 위 방법들은 어플리케이션을 만드는 개발팀이 해야만 했다.
메트릭을 노출하는 엔드포인트를 만들고, 모든 요청에 span을 넣어서 트레이싱이 가능하게 한다던지..
요청이 실패했을 때 알아서 재시작을 하게 한다던지..
이를 위해 Eureka, Zuul 등의 다양한 언어 라이브러리들이 등장하였고 지금도 쓰이고 있기는 하다.
그러나 MSA 환경에서 효율적인 전략이라고 하기에는 역시나 많은 문제가 있다.
- 라이브러리와 비즈니스 로직의 결합도
- 각 라이브러리가 효율적으로 동작하기 위해, 비즈니스 로직 중간에 코드가 삽입돼야 하는 경우가 생길 수 있다.
- 코드가 잘 정제됐다면 결합도를 느슨하게 하는 것이 가능하겠지만, 이조차도 높은 러닝 커브를 유발하게 된다.
- 높은 결합도는 당연히 운영 부담도를 높이며, 종속성을 높여 기술 부채를 야기할 수 있다.
- 서비스 간 결합도
- 언어 라이브러리는 저마다의 규약이 정해져있는 경우가 많고, 이로부터 한 언어 내에서도 사용할 수 있는 기술 스택이 한정되는 결과를 초래할 수 있다.
- 자칫하면 모든 서비스를 전부 같은 식으로 개발해야 하는 경직된 환경을 조장할 수 있다.
- 다양한 언어 환경을 사용하지 못하게 된다는 것은 말할 것도 없다.
운영팀으로서는 이 해결책들을 개발팀한테 "해 줘"해야 하는 입장이긴 하나, 이러한 방식은 개발팀의 업무에 지장을 주기도 하는 동시에 전체 운영 환경의 유연성을 해친다는 것이다.
서비스 운영팀에서 해결하기 - 네트워크 레이어 분리
위 문제들은 운영 상 발생하는 문제이기도 한데, 비즈니스 로직에 집중을 해야 하는 개발팀이 주체적으로 대응하는 방식은 매우 아쉬운 해결책이다.
또한 재시도, 트레이싱 등의 해결책들은 어플리케이션 기능과도 관련도 없고 언어와 프레임워크에 한정해 고려해야 하는 요소들도 아니다.
이로부터 자연스럽게 이것들을 서비스 관리를 책임지는 운영팀에서 처리할 수 있는 방안이 강구되기 시작했고, 그렇게 등장한 것이 바로 서비스 메시이다.
위 문제와 해결 방법들은 사실 전부 네트워크와 관련되는 문제라는 공통 분모를 가지고 있다.
이로부터 어플리케이션 간에 이뤄져야 하는 네트워크 관련 기능과 이슈들은 아예 하나의 레이어로 분리하여 관리하는 것.
서비스 메시 레이어가 있으면 어플리케이션의 세팅이 어떤지 상관 없이 모든 네트워크 기능들을 운영 단계에서 해결할 수 있게 된다.
이것이 바로 서비스 메시의 등장 배경이자, 주된 기능이라고 할 수 있다!
구조
클라우드넷 스터디의 자료가 굉장히 명쾌하게 이해된다고 생각해 가져왔다.
서비스 메시는 3번의 구조를 가지고 있는데, 왜 이런 구조를 가지고 있는지 단계적으로 이해하기 좋다.
데이터 플레인
배경에서 나온 내용에 이어서, 어떻게 어플리케이션과 별개로 네트워크 기능들을 처리한다는 말인가?
구체적으로는 이렇게 모든 서비스 앞단에 네트워크 기능을 처리하는 프록시를 두는 방식으로 이뤄진다.
이 프록시 서버가 서비스가 주고받을 트래픽을 먼저 받아서 스팬을 달던, 적절한 경로를 설정해주던 실패하면 재시도를 해주던, 암호화를 해주던!
트래픽의 모든 기능을 이해할 수 있는 L7 프록시로서 모든 기능을 처리하면 되는 것이다.
어플리케이션에 일체 설정을 하지 않고 어떻게 프록시가 트래픽을 처리할 수 있게 설정하는지 궁금할 수 있다.
이건 네트워크 트래픽이 흐르는 구조를 생각하면 쉽게 이해할 수 있다.
어떤 프로세스가 트래픽을 보낼 때는 네트워크 계층 구조를 거치는데, 어플리케이션은 이때 상위 계층의 구조만을 이해하고 트래픽을 처리한다.
그렇다면 해당 트래픽이 아래 계층을 타서 L1까지 이어져 다른 어플리케이션으로 가서 다시 L7의 트래픽으로 인식되기 전까지, 그 아래 계층에서 트래픽을 조작하면 간단하게 프록시가 트래픽을 받아서 처리하게 만들 수 있다.
가령 iptables를 이용하면 L3, L4 단계의 트래픽을 조작하는 것이 가능한데, 이걸 인프라 단계에서 설정해버리면 모든 서비스의 트래픽을 마음대로 조절하는 것이 가능하다.
그래서 서비스 메시에서는 서비스마다 트래픽이 프록시를 거치게 만들어 이러한 플로우를 달성한다.
당연히 각 서비스는 자신의 앞단에 프록시가 있는지 알 필요도 없고 알지도 못한다.
컨트롤 플레인
무수한 서비스가 있을 텐데 여기에 일일히 프록시를 주입하고 설정하는 것은 당연히 어려운 일이다.
그래서 서비스 메시에서는 보통 각 서비스에 부착되는 프록시 구조 일체의 영역을 데이터 플레인으로 두고, 이를 관리하는 컨트롤 플레인을 따로 구축한다.
운영 팀은 컨트롤 플레인에 각종 설정을 하고, 컨트롤 플레인은 설정에 기반하여 각 프록시를 세팅하고 관리하는 역할을 수행한다.
이스티오의 경우 컨트롤 플레인 istiod는 트래픽 라우팅 관리, 통신 암호화, 클러스터 환경 내 인증 인가 등의 기능을 수행한다.
이를 통해 서비스 메시 환경의 관리를 원활하게 수행할 수 있게 되는 것이다.
비단 데이터 플레인의 프록시를 조작하는 역할로서의 컨트롤 플레인을 상정하지 않더라도, 네트워크를 총괄하는 중앙 집중형 시스템을 구축한다는 것은 충분히 메리트있는 선택지이기는 하다.
이 부분에 대해서는 서비스 메시와 [[#다른 시스템과의 비교]]를 통해 조금 더 짚어보도록 하겠다.
기능
이제 서비스 메시라는 것은 하나의 추상화된 레이어를 일컫는 개념이자, 이를 활용하는 아키텍처라는 것을 명확히 할 수 있을 것이다.
그리고 서비스 메시는 인프라 레이어와 밀접한 연관을 가지는 어플리케이션의 네트워크 기능을 전적으로 담당하는 역할을 수행한다.
그럼 구체적으로 서비스 메시를 통해 어떤 것들을 할 수 있는지를 구체화시켜보자.
- 서비스 회복성, 탄력성
- 서비스 디스커버리를 통해 건강한 엔드포인트만 트래픽이 흐르도록 설정한다.
- 네트워크가 계속 안정적일 수 있도록 실패 지점을 분리하는 것을 서킷 브레이커라고 부른다.
- 비정상적인 트래픽은 타임아웃을 걸고 요청에 대한 실패를 재시도하는 식으로 대응한다.
- 서비스 디스커버리를 통해 건강한 엔드포인트만 트래픽이 흐르도록 설정한다.
- 관측 가능성 설정
- 서비스 간 트래픽의 흐름을 파악할 수 있도록 트레이싱 설정을 한다.
- 트레이싱은 관측 가능성#Trace을 보자.
- 요청 처리 시간, 수행 결과 등을 메트릭과 로그를 통해 볼 수 있도록 설정한다.
- 서비스 간 트래픽의 흐름을 파악할 수 있도록 트레이싱 설정을 한다.
- 트래픽 컨트롤 기능 - 가장 당연한 기능이긴 한데, 조금 더 세밀한 컨트롤이 가능하도록 돕는다.
- 무중단 배포 중 어떤 헤더를 가진 트래픽만 새 버전으로 라우팅한다.
- 트래픽을 가중치 기반으로 일정 비율로 분산한다.
- 다른 서브 패스를 가진 요청 주소에 따라 다른 서비스로 라우팅한다.
- 클러스터 외부 트래픽을 받거나 내보내는 게이트웨이를 설정한다.
- 보안
- 통신 간 암호화(mTLS)를 설정한다.
- 트래픽에 신원을 부여하고 이를 기반으로 인증을 수행한다.
- 정책 적용
- 운영 상황에 적절한 각종 정책을 설정하고 이를 동적으로 적용한다.
호고곡.. 어플리케이션에 영향을 주지 않고 이런 것들을 할 수 있다니 넘나 좋다!
적합한 사용 케이스 - 고려 사항
이렇게만 말하면 서비스를 운용할 때 반드시 서비스 메시를 사용해야 할 것처럼 들리기도 하지만, 당연히 서비스 메시를 도입하는 것에도 트레이드 오프는 존재한다.
서비스 메시가 적합한 경우는 인프라 환경과 어플리케이션이 명확하게 분리되어 운용될 수 있는 환경이다.
- 어플리케이션
- 자체 배포 주기를 가지고 있으며 배포 자동화가 구축돼있다.
- 기능 별 서비스가 분리된 MSA이고 세밀하게 팀이 분화돼있다.
- 인프라 환경
- 다양한 플랫폼을 가질 수 있다(쿠버, 단순 VM, 클라우드 등).
- 오토스케일링 기능이 구축돼있다.
이럴 때, 인프라 환경과 어플리케이션의 관심 영역과 라이프사이클은 느슨한 결합도를 가질 수록 운영이 간편해지는데, 이때 중간다리로서 서비스 메시를 두는 것은 매우 효과적이다.
이런 상황에서 서비스 메시는 플랫폼과 코드를 이어주는 연결 조직 역할을 수행할 수 있다.
그렇다면 서비스 메시를 도입함으로써 가지게 되는 불편함은 무엇이 있을까?
(이스티오를 도입할 수 있는 장점은 이스티오를 도입하지 않아도 이룰 수 있다는 많은 실무자들의 많은 푸념을 많이 봤다..)
- 블랙 박스 레이어
- 요청 경로 상에 프록시라는 미들웨어가 하나 추가되므로, 이 방식이 익숙하지 않은 사람에게는 오히려 디버깅을 어렵게 한다.
- 테넌시
- 반대로, 네트워크 자원의 적절한 격리 모델, 물리 자원 활용 전략 등에 대한 고민이 필요하다.
- 아래에서 볼 MSA를 위한 다른 방식들과 비교했을 때는 낫지만 테넌시를 고려할 때 항상 나오는 시끄러운 이웃 문제를 완전히 배제할 수 없다는 것이다.
- 전문성
- 서비스 메시는 서비스 간 모든 네트워크를 관리하는 통합체로서 기능하며, 서비스가 많아질수록 사용 가치가 올라간다.
- 그만큼 서비스 메시를 도입하면 서비스 메시 그 자체의 중요도가 굉장히 높아지며, 이를 제대로 활용할 조직 역량이 요구된다.
- 이는 곧 서비스 메시 자체에 대한 전문성을 필요로 하다는 것으로, 서비스 메시가 가지는 복잡성을 제대로 이해해야 한다.
- 조직 내에서 절차와 거버넌스를 어떻게 설정하고 통합할지 심도 깊은 고민이 필요한데, 이때 높은 전문성은 진입장벽이 된다.
다른 시스템과의 비교
Enterprise Service Bus
ESB는 서비스 지향 아키텍처(Service Oriented Architecture)를 구축하는 방향성으로 나온 또다른 아키텍처이다.[1]
ESB는 하나의 서비스 버스(트래픽을 운송하는 수단)을 상정하는데, 서비스 메시와 마찬가지로 이것은 서비스 입장에서는 암묵적인 파트너(silent partener)로서 서비스는 이를 몰라도 되도록 구성된다.
그러나 서비스 메시와 다른 몇 가지 지점이 있다.
- ESB 비즈니스 로직을 기반으로 버스에 들어온 트래픽을 어디로 라우팅해야 하는지 결정한다.
- 이로 인해 컨텐츠 기반 라우팅 기능을 제공할 수 있는 아키텍처로서 서비스 종속적인 기능도 가진다.
- 컨텐츠 기반이라는 것은 어플리케이션 로직에 대한 분석과 이해가 들어가는 작업이다.
- 즉, 어플리케이션 네트워킹의 영역에 깊게 관여하게 되며, 이러한 구성을 위해 개발팀의 협력이 필수적이다.
- 위 그림처럼 중앙 집중형으로 트래픽을 관리하며 거대한 단일 장애 지점을 만드는 꼴이다.
서비스 메시는 서비스가 자신 아래 어떤 메시가 구성돼있는지 몰라도 되는 한편, 서비스 메시도 자신이 관리할 서비스가 어떻게 구성돼있는지 자세히 알 필요가 없다.
각 서비스가 어떤 서비스와 통신을 해야하는지, 네트워크 구성도에 대한 정보만 알고 있다면 서비스 메시는 운영팀이 알아서 구성할 수 있다.
API Gateway
api 게이트웨이 역시 위의 구조와 상당히 비슷한데, 하나의 게이트웨이를 두고 외부 노출 엔드포인트와 클러스터 내부의 엔드포인트를 전부 관리하는 방식이다.
ESB와 같이 비즈니스 로직에 깊게 관여하진 않고, 하나의 중앙 경로 역할만 수행한다.
그냥 흔히 엔드포인트를 기반으로 라우팅할 백엔드를 두는 프록시를 생각하면 된다.
대체로 엔드포인트 경로를 기반으로 라우팅할 서비스가 결정되는데, 이 역시 중앙 집중형 시스템으로 인해 단일 장애 지점이 생기는 꼴이라 할 수 있다.
그렇지만 각 서비스가 통신을 하기 위해 하나의 홉을 더 거치게 되므로 비효율이 야기된다.
또 서비스 메시에서 할 수 있는 서킷 브레이커나 복원성에 대한 기능들까지 감안된 아키텍처도 아니다.
관련 문서
이름 | noteType | created |
---|---|---|
서비스 메시 | knowledge | 2024-06-13 |
Gateway API | knowledge | 2025-01-06 |
Amazon VPC Lattice | knowledge | 2025-04-23 |
pilot-agent | knowledge | 2025-04-28 |
Kiali | knowledge | 2025-04-28 |
사이드카 모드 | knowledge | 2025-05-18 |
메시 배포 모델 | knowledge | 2025-05-21 |
앰비언트 모드 | knowledge | 2025-06-02 |
1W - 서비스 메시와 이스티오 | published | 2025-04-10 |
4W - 번외 - 트레이싱용 심플 메시 서버 개발 | published | 2025-05-03 |
6W - 이스티오 컨트롤 플레인 성능 최적화 | published | 2025-05-18 |
8W - 엔보이와 iptables 뜯어먹기 | published | 2025-06-01 |
E-이스티오 컨트롤 플레인 성능 최적화 | topic/explain | 2025-05-18 |
E-이스티오의 데이터 플레인 트래픽 세팅 원리 | topic/explain | 2025-05-27 |
참고
이 개념을 정립하기 위해 나는 두 가지 책을 참고했다.
첫번째로 간단한 개념을 잡기 위해 그림으로 공부하는 마이크로서비스 구조를 읽었다.
이후로 Istio in Action을 읽으며 개념을 본격화하며 자료도 참고했다.
또한 Istio 1기 - Istio Hands-on에서 공부하며 자료도 참고하는 동시에 더 확실하게 내 개념을 정리했다.